package com.aek.ebey.sys.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.aek.common.core.base.BaseServiceImpl;
import com.aek.common.core.exception.ExceptionFactory;
import com.aek.ebey.sys.core.SysConstants;
import com.aek.ebey.sys.enums.TenantAuditStatus;
import com.aek.ebey.sys.enums.TenantOrigin;
import com.aek.ebey.sys.enums.TenantType;
import com.aek.ebey.sys.mapper.SysTenantMapper;
import com.aek.ebey.sys.model.SysDept;
import com.aek.ebey.sys.model.SysRole;
import com.aek.ebey.sys.model.SysRoleUser;
import com.aek.ebey.sys.model.SysTenant;
import com.aek.ebey.sys.model.SysUser;
import com.aek.ebey.sys.model.query.TenantQuery;
import com.aek.ebey.sys.service.SysDeptService;
import com.aek.ebey.sys.service.SysRoleService;
import com.aek.ebey.sys.service.SysRoleUserService;
import com.aek.ebey.sys.service.SysTenantModuleService;
import com.aek.ebey.sys.service.SysTenantService;
import com.aek.ebey.sys.service.SysUserService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.enums.SQLlikeType;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.collect.Lists;

/**
 * <p>
 * 医院机构表 服务实现类
 * </p>
 *
 * @author aek
 * @since 2017-05-06
 */
@Service
@Transactional
public class SysTenantServiceImpl extends BaseServiceImpl<SysTenantMapper, SysTenant> implements SysTenantService {

	@Autowired
	private SysTenantMapper tenantMapper;

	@Autowired
	private SysUserService userService;

	@Autowired
	private SysDeptService deptService;

	@Autowired
	private SysRoleService roleService;

	@Autowired
	private SysTenantModuleService tenantModuleService;

	@Autowired
	private SysRoleUserService roleUserService;

	@Override
	public void createSubTenant(SysTenant tenant, SysUser admin) {

		SysUser createUser = this.userService.selectById(tenant.getCreateBy());
		if (null == createUser) {
			throw ExceptionFactory.create("G_004");
		}
		// 重复验证

		SysTenant parentTenant = this.selectById(tenant.getParentId());

		Date currTime = new Date();

		// 处理子机构创建
		this.disposeSubTenant(tenant);

		this.initParentIds(tenant, parentTenant);

		// 非系统管理员创建继承父机构到期时间及父机构类型
		if (!createUser.getAdminFlag()) {
			tenant.setExpireTime(parentTenant.getExpireTime());
			tenant.setTenantType(parentTenant.getTenantType());
		}

		tenant.setCreateBy(createUser.getId());
		tenant.setCreateTime(currTime);
		tenant.setOrigin(TenantOrigin.BACK_CREATE.getNumber());
		tenant.setAuditStatus(TenantAuditStatus.THROUGH.getNumber());
		tenant.setUpdateBy(createUser.getId());
		tenant.setUpdateTime(currTime);
		// 处理机构类型数据
		this.disposeCustomData(tenant);
		this.insert(tenant);

		// 初始化机构部门信息(根节点默认与机构名称相同)
		this.deptService.initTenantDept(tenant);

		// 初始化模块
		this.tenantModuleService.initTenantModule(tenant.getId());

		// 初始化机构角色信息
		this.roleService.initTenantRole(tenant.getId());

		// 初始化机构管理员
		if (null != admin) {
			this.userService.initTenantAdminUser(tenant, admin);
		}

		// 更新新建机构关联信息
		this.updateById(tenant);
	}

	@Override
	public void modifySubTenant(SysTenant tenant, SysUser admin) {
		Date currTime = new Date();
		tenant.setUpdateTime(currTime);

		SysUser updateUser = this.userService.selectById(tenant.getUpdateBy());
		if (null == updateUser) {
			throw ExceptionFactory.create("G_005");
		}

		// 处理子机构限制
		this.disposeSubTenant(tenant);

		// 机构到期时间，级联更新子机构
		if (updateUser.getAdminFlag() && tenant.getExpireTime() != null) {

			List<SysTenant> subTenants = this.findAllSubTenant(tenant.getId());
			for (SysTenant subTenant : subTenants) {
				subTenant.setExpireTime(tenant.getExpireTime());
			}
			if (CollectionUtils.isNotEmpty(subTenants)) {
				this.updateBatchById(subTenants);
			}
		} else {
			// 用户租户无法修改有效期
			tenant.setExpireTime(null);
		}

		// 处理机构类型数据
		this.disposeCustomData(tenant);
		this.updateById(tenant);

		// 修改机构根部门名称
		SysDept rootDept = this.deptService.findRootDeptByTenantId(tenant.getId());
		rootDept.setName(tenant.getName());
		rootDept.setUpdateTime(currTime);
		this.deptService.updateById(rootDept);

		// 创建机构管理员
		if (null != admin) {
			this.userService.initTenantAdminUser(tenant, admin);
		}
	}

	/**
	 * 初始化parentIds
	 * 
	 * @param tenant
	 *            当前机构
	 * @param parentTenant
	 *            父机构
	 */
	private void initParentIds(SysTenant tenant, SysTenant parentTenant) {
		String parentIds = null;
		if (parentTenant == null) {
			tenant.setParentId(SysConstants.ROOT_PARENT);
			tenant.setParentIds(SysConstants.ROOT_PARENT_STR);
		} else {
			parentIds = parentTenant.getParentIds() + "," + tenant.getParentId();
			tenant.setParentId(parentTenant.getId());
			tenant.setParentIds(parentIds);
		}
	}

	/**
	 * 处理子机构创建数量限制
	 * 
	 * @param tenant
	 */
	private void disposeSubTenant(SysTenant tenant) {
		SysTenant parentTenant = null;

		// 创建
		if (null == tenant.getId()) {
			parentTenant = this.selectById(tenant.getParentId());

			if (parentTenant == null) {
				throw ExceptionFactory.create("O_002");
			}

			// 判断父机构创建子机构的限制次数
			int tenantNum = (tenant.getSubTenantLimit() == null ? 0 : tenant.getSubTenantLimit()) + 1; // 加上当前机构
			int parentSpareNum = parentTenant.getSubTenantLimit() - parentTenant.getSubTenant(); // 父机构剩余创建数量
			if (parentSpareNum < tenantNum) {
				throw ExceptionFactory.create("O_006");
			}
			parentTenant.setSubTenant(parentTenant.getSubTenant() + tenantNum);

		} else {
			// 当前机构原始信息
			SysTenant beforeTenant = this.selectById(tenant.getId());

			// 父机构
			parentTenant = this.selectById(beforeTenant.getParentId());

			// 是否修改创建子机构限制
			if (tenant.getSubTenantLimit() != null) {
				if (!(beforeTenant.getSubTenantLimit().equals(tenant.getSubTenantLimit()))) {

					// 当前机构已创建子租户大于修改创建限制
					if (beforeTenant.getSubTenant() > tenant.getSubTenantLimit()) {
						throw ExceptionFactory.create("O_009", String.valueOf(beforeTenant.getSubTenant()));
					}

					// 本次使用创建数量
					int tenantNum = tenant.getSubTenantLimit() + 1;

					// 上次使用创建数量
					int beforeTenantNum = beforeTenant.getSubTenantLimit() + 1;

					// 父机构原始已创建数量
					int parentBeforeTenantNum = parentTenant.getSubTenant() - beforeTenantNum;

					// 父机构剩余创建数量
					int parentSpareNum = parentTenant.getSubTenantLimit() - parentBeforeTenantNum;

					if (parentSpareNum < tenantNum) {
						throw ExceptionFactory.create("O_006");
					}

					parentTenant.setSubTenant(parentBeforeTenantNum + tenantNum);
				}
			}
		}

		// 更新父机构
		this.updateById(parentTenant);
	}

	/**
	 * 处理机构类型数据
	 * 
	 * @param tenant
	 */
	private void disposeCustomData(SysTenant tenant) {

		Integer tenantType = tenant.getTenantType();
		// 判断机构类型
		if (TenantType.HOSPITAL.getNumber().equals(tenantType)) {
			tenant.setCustomData(JSON.toJSONString(tenant.getHplTenant()));
		}
		if (TenantType.SUPERVISE.getNumber().equals(tenantType)) {
			tenant.setCustomData(JSON.toJSONString(tenant.getSuperviseTenant()));
		}
	}

	@Override
	public List<SysTenant> findAllSubTenant(Long tenantId) {
		SysTenant tenant = this.selectById(tenantId);

		Wrapper<SysTenant> wrapper = new EntityWrapper<SysTenant>();
		wrapper.eq("del_flag", false).like("parent_ids", tenant.getParentIds() + "," + tenant.getId(),
				SQLlikeType.RIGHT);

		return this.selectList(wrapper);
	}

	@Override
	public void stopTenantById(Long tenantId) {
		Date currTime = new Date();
		SysTenant tenant = this.selectById(tenantId);
		tenant.setEnable(false);
		tenant.setUpdateTime(currTime);
		this.tenantMapper.updateById(tenant);
	}

	@Override
	public void deleteTenantById(Long tenantId) {
		Date currTime = new Date();
		SysTenant tenant = this.selectById(tenantId);
		tenant.setDelFlag(true);
		tenant.setUpdateTime(currTime);
		this.tenantMapper.updateById(tenant);
	}

	@Override
	public void recoverTenantById(Long tenantId) {
		Date currTime = new Date();
		SysTenant tenant = this.selectById(tenantId);

		tenant.setEnable(true);
		tenant.setUpdateTime(currTime);
		this.tenantMapper.updateById(tenant);
	}

	@Override
	public void delayTenant(Long updateBy, Long tenantId, Integer days) {
		SysUser user = this.userService.selectById(updateBy);

		// 只有AEK 用户可操作
		if (!user.getAdminFlag()) {
			throw ExceptionFactory.create("G_010");
		}
		SysTenant tenant = this.selectById(tenantId);

		// null 为永久有效不需要操作
		if (tenant.getExpireTime() == null) {
			throw ExceptionFactory.create("O_010");
		}

		if (days != null && days > 0) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(tenant.getExpireTime());
			int day = calendar.get(Calendar.DATE);
			calendar.set(Calendar.DATE, day + days);

			Date expireTime = calendar.getTime();
			tenant.setExpireTime(expireTime);

			// 级联更新子机构
			List<SysTenant> subTenants = this.findAllSubTenant(tenantId);
			if (CollectionUtils.isNotEmpty(subTenants)) {
				for (SysTenant subTenant : subTenants) {
					subTenant.setExpireTime(expireTime);
				}
			}
			subTenants.add(tenant);
			this.updateBatchById(subTenants);
		}
	}

	@Override
	public Page<SysTenant> findPageByKeyword(TenantQuery query) {
		Page<SysTenant> page = query.getPage();

		Wrapper<SysTenant> wrapper = new EntityWrapper<SysTenant>();
		wrapper.eq("parent_id", query.getTenantId()).eq("del_flag", false);

		if (query.getTrial() != null) {
			wrapper.eq("trial", query.getTrial());
		}

		if (query.getOrigin() != null) {
			wrapper.eq("origin", query.getOrigin());
		}

		if (query.getAuditStatus() != null) {
			wrapper.eq("audit_status", query.getAuditStatus());
		}

		if (query.getTenantType() != null) {
			wrapper.eq("tenant_type", query.getTenantType());
		}

		if (query.getCommercialUse() != null) {
			wrapper.eq("commercial_use", query.getCommercialUse());
		}

		if (query.getEnable() != null) {
			wrapper.eq("enable", query.getEnable());
		}

		String keyword = StringUtils.trimToNull(query.getKeyword());

		if (keyword != null) {
			wrapper.andNew("name LIKE {0} OR id LIKE {0}", "%" + keyword + "%");
		}
		return this.selectPage(page, wrapper);
	}

	@Override
	public List<SysTenant> findUserSeeTenant(Long userId) {
		List<SysTenant> tenants = Lists.newArrayList();
		SysUser user = this.userService.selectById(userId);

		// 当前用户拥有admin角色,直接查询全部下级机构（包含停用机构,管理员可以启用该机构）
		SysRole adminRole = this.roleUserService.findUserAdminRole(userId);
		if (adminRole != null) {
			tenants.add(this.selectById(user.getTenantId()));
			tenants.addAll(this.findAllSubTenant(user.getTenantId()));
			return tenants;
		}

		// 查询拥有角色的机构
		Wrapper<SysRoleUser> wrapper = new EntityWrapper<SysRoleUser>();
		wrapper.eq("enable", true).eq("user_id", userId).groupBy("tenant_id");
		List<SysRoleUser> roleUsers = this.roleUserService.selectList(wrapper);

		for (SysRoleUser roleUser : roleUsers) {
			SysTenant tenant = this.selectById(roleUser.getTenantId());
			// 未 停用删除
			if (tenant.getEnable() == true && tenant.getDelFlag() == false) {
				tenants.add(tenant);
			}
		}
		return tenants;
	}
}
